package top.lixunda.ecommerce.server.good.api.entity.dto;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.ImmutableMap;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import top.lixunda.common.utils.ObjectValidators;
import top.lixunda.ecommerce.server.business.api.condition.ILambdaConvertQueryWrapperDTO;
import top.lixunda.ecommerce.server.business.api.entity.dto.OrderByDTO;
import top.lixunda.ecommerce.server.good.api.entity.db.GoodOrderDO;
import top.lixunda.ecommerce.server.good.api.entity.db.OrderDetailDO;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 订单详细信息查询DTO，管理员权限接口使用
 *
 * @author Xumda
 * @version time:2020/2/24 17:16
 */
@SuppressWarnings("Duplicates")
@ApiModel(value = "订单详细信息查询DTO", description = "订单详细信息查询DTO，管理员权限接口使用")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class AdminOrderDetailQueryDTO extends OrderByDTO
        implements ILambdaConvertQueryWrapperDTO<GoodOrderDO, OrderDetailDO> {

    /**
     * 订单id
     */
    @ApiModelProperty("订单id")
    private List<Integer> ids;

    /**
     * 店铺id
     */
    @ApiModelProperty("店铺id")
    private List<Integer> storeId;

    /**
     * 创建时间
     */
    @ApiModelProperty("创建时间")
    private LocalDateTime createTimeBegin;

    /**
     * 创建时间
     */
    @ApiModelProperty("创建时间")
    private LocalDateTime createTimeEnd;

    /**
     * 付款时间
     */
    @ApiModelProperty("付款时间")
    private LocalDateTime priceTimeBegin;

    /**
     * 付款时间
     */
    @ApiModelProperty("付款时间")
    private LocalDateTime priceTimeEnd;

    /**
     * 发货时间
     */
    @ApiModelProperty("发货时间")
    private LocalDateTime goodTimeBegin;

    /**
     * 发货时间
     */
    @ApiModelProperty("发货时间")
    private LocalDateTime goodTimeEnd;

    /**
     * 成交时间
     */
    @ApiModelProperty("成交时间")
    private LocalDateTime endTimeBegin;

    /**
     * 成交时间
     */
    @ApiModelProperty("成交时间")
    private LocalDateTime endTimeEnd;

    /**
     * 最终需支付价格，实付款
     */
    @ApiModelProperty("最终需支付价格，实付款")
    private BigDecimal priceBegin;

    /**
     * 最终需支付价格，实付款
     */
    @ApiModelProperty("最终需支付价格，实付款")
    private BigDecimal priceEnd;

    /**
     * 支付方式
     */
    @ApiModelProperty("支付方式")
    private List<String> payType;

    /**
     * 支付订单号
     */
    @ApiModelProperty("支付订单号")
    private List<String> payId;

    /**
     * 物流单号
     */
    @ApiModelProperty("物流单号")
    private List<String> logisticsNumber;

    /**
     * 物流类别
     */
    @ApiModelProperty("物流类别")
    private List<String> logisticsType;

    /**
     * 订单状态，待支付，未支付，代发货，运输中，也签收，也完结，待退款，已退款，已取消，审查中
     */
    @ApiModelProperty(value = "订单状态", notes = "待支付，未支付，代发货，运输中，也签收，也完结，待退款，已退款，已取消，审查中")
    private List<String> state;

    /**
     * 处理时间相关
     *
     * @param wrapper LambdaQueryWrapper
     */
    private void dealWrapperTime(LambdaQueryWrapper<GoodOrderDO> wrapper) {
        if (ObjectValidators.isNotEmpty(this.createTimeBegin)) {
            wrapper.ge(GoodOrderDO::getCreateTime, this.createTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(this.createTimeEnd)) {
            wrapper.le(GoodOrderDO::getCreateTime, this.createTimeEnd);
        }
        if (ObjectValidators.isNotEmpty(this.priceTimeBegin)) {
            wrapper.ge(GoodOrderDO::getPriceTime, this.priceTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(this.priceTimeEnd)) {
            wrapper.le(GoodOrderDO::getPriceTime, this.priceTimeEnd);
        }
        // 发货时间
        if (ObjectValidators.isNotEmpty(this.goodTimeBegin)) {
            wrapper.ge(GoodOrderDO::getGoodTime, this.goodTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(this.goodTimeEnd)) {
            wrapper.le(GoodOrderDO::getGoodTime, this.goodTimeEnd);
        }
        // 完成时间
        if (ObjectValidators.isNotEmpty(this.endTimeBegin)) {
            wrapper.ge(GoodOrderDO::getEndTime, this.endTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(this.endTimeEnd)) {
            wrapper.le(GoodOrderDO::getEndTime, this.endTimeEnd);
        }
    }

    /**
     * 排序字段映射
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private static final Map<String, SFunction<GoodOrderDO, ?>> GOOD_ORDER_COLUMNS =
            new ImmutableMap.Builder<String, SFunction<GoodOrderDO, ?>>()
                    .put("orderId", GoodOrderDO::getId)
                    .put("userId", GoodOrderDO::getUserId)
                    .put("userName", GoodOrderDO::getUserName)
                    .put("storeId", GoodOrderDO::getStoreId)
                    .put("storeName", GoodOrderDO::getStoreName)
                    .put("createTime", GoodOrderDO::getCreateTime)
                    .put("priceTime", GoodOrderDO::getPriceTime)
                    .put("goodTime", GoodOrderDO::getGoodTime)
                    .put("endTime", GoodOrderDO::getEndTime)
                    .put("goodsPrice", GoodOrderDO::getGoodsPrice)
                    .put("totalFreight", GoodOrderDO::getFreight)
                    .put("haveFreightInsu", GoodOrderDO::getHaveFreightInsu)
                    .put("freightInsu", GoodOrderDO::getFreightInsu)
                    .put("redEnvelope", GoodOrderDO::getRedEnvelope)
                    .put("totalIntegral", GoodOrderDO::getIntegral)
                    .put("totalPrice", GoodOrderDO::getPrice)
                    .put("payType", GoodOrderDO::getPayType)
                    .put("payId", GoodOrderDO::getPayId)
                    .put("logisticsNumber", GoodOrderDO::getLogisticsNumber)
                    .put("logisticsType", GoodOrderDO::getLogisticsType)
                    .put("startAddressId", GoodOrderDO::getStartAddressId)
                    .put("endAddressId", GoodOrderDO::getEndAddressId)
                    .put("orderState", GoodOrderDO::getState)
                    .put("message", GoodOrderDO::getMessage)
                    .put("orderRemark", GoodOrderDO::getRemark)
                    .build();

    /**
     * 分页条件，主表
     *
     * @return 条件构造器 LambdaQueryWrapper
     */
    @Override
    public LambdaQueryWrapper<GoodOrderDO> toPageWrapper() {
        LambdaQueryWrapper<GoodOrderDO> wrapper = new LambdaQueryWrapper<>();
        // 订单id
        if (ObjectValidators.isNotEmpty(ids)) {
            wrapper.and(subWrapper ->
                    ids.forEach(
                            item -> subWrapper.or().eq(GoodOrderDO::getId, item)
                    ));
        }
        // 店铺id
        if (ObjectValidators.isNotEmpty(storeId)) {
            wrapper.and(subWrapper ->
                    storeId.forEach(
                            item -> subWrapper.or().eq(GoodOrderDO::getStoreId, item)
                    ));
        }
        // 实付款
        if (ObjectValidators.isNotEmpty(this.priceBegin)) {
            wrapper.ge(GoodOrderDO::getPrice, this.priceBegin);
        }
        if (ObjectValidators.isNotEmpty(this.priceEnd)) {
            wrapper.le(GoodOrderDO::getPrice, this.priceEnd);
        }
        // 支付方式
        if (ObjectValidators.isNotEmpty(payType)) {
            wrapper.and(subWrapper ->
                    payType.forEach(
                            item -> subWrapper.or().eq(GoodOrderDO::getPayType, item)
                    ));
        }
        // 支付订单号
        if (ObjectValidators.isNotEmpty(payId)) {
            wrapper.and(subWrapper ->
                    payId.forEach(
                            item -> subWrapper.or().eq(GoodOrderDO::getPayId, item)
                    ));
        }
        // 物流类别
        if (ObjectValidators.isNotEmpty(logisticsType)) {
            wrapper.and(subWrapper ->
                    logisticsType.forEach(
                            item -> subWrapper.or().eq(GoodOrderDO::getLogisticsType, item)
                    ));
        }
        // 物流单号
        if (ObjectValidators.isNotEmpty(logisticsNumber)) {
            wrapper.and(subWrapper ->
                    logisticsNumber.forEach(
                            item -> subWrapper.or().eq(GoodOrderDO::getLogisticsNumber, item)
                    ));
        }
        // 状态
        if (ObjectValidators.isNotEmpty(state)) {
            wrapper.and(subWrapper ->
                    state.forEach(
                            item -> subWrapper.or().eq(GoodOrderDO::getState, item)
                    ));
        }
        dealWrapperTime(wrapper);
        dealWithOrderBy(wrapper, GOOD_ORDER_COLUMNS);
        return wrapper;
    }

    /**
     * 排序字段映射
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private static final Map<String, SFunction<OrderDetailDO, ?>> COLUMNS =
            new ImmutableMap.Builder<String, SFunction<OrderDetailDO, ?>>()
                    .put("orderId", OrderDetailDO::getOrderId)
                    .put("userId", OrderDetailDO::getUserId)
                    .put("userName", OrderDetailDO::getUserName)
                    .put("storeId", OrderDetailDO::getStoreId)
                    .put("storeName", OrderDetailDO::getStoreName)
                    .put("createTime", OrderDetailDO::getCreateTime)
                    .put("priceTime", OrderDetailDO::getPriceTime)
                    .put("goodTime", OrderDetailDO::getGoodTime)
                    .put("endTime", OrderDetailDO::getEndTime)
                    .put("goodsPrice", OrderDetailDO::getGoodsPrice)
                    .put("totalFreight", OrderDetailDO::getTotalFreight)
                    .put("haveFreightInsu", OrderDetailDO::getHaveFreightInsu)
                    .put("freightInsu", OrderDetailDO::getFreightInsu)
                    .put("redEnvelope", OrderDetailDO::getRedEnvelope)
                    .put("totalIntegral", OrderDetailDO::getTotalIntegral)
                    .put("totalPrice", OrderDetailDO::getTotalPrice)
                    .put("payType", OrderDetailDO::getPayType)
                    .put("payId", OrderDetailDO::getPayId)
                    .put("logisticsNumber", OrderDetailDO::getLogisticsNumber)
                    .put("logisticsType", OrderDetailDO::getLogisticsType)
                    .put("startAddressId", OrderDetailDO::getStartAddressId)
                    .put("endAddressId", OrderDetailDO::getEndAddressId)
                    .put("orderState", OrderDetailDO::getOrderState)
                    .put("message", OrderDetailDO::getMessage)
                    .put("orderRemark", OrderDetailDO::getOrderRemark)
                    .put("subId", OrderDetailDO::getSubId)
                    .put("goodId", OrderDetailDO::getGoodId)
                    .put("subGoodId", OrderDetailDO::getSubGoodId)
                    .put("subGoodName", OrderDetailDO::getSubGoodName)
                    .put("subPrice", OrderDetailDO::getSubPrice)
                    .put("subCount", OrderDetailDO::getSubCount)
                    .put("subTotal", OrderDetailDO::getSubTotal)
                    .put("subFreight", OrderDetailDO::getSubFreight)
                    .put("otherPreferential", OrderDetailDO::getOtherPreferential)
                    .put("otherPreferentialDesc", OrderDetailDO::getOtherPreferentialDesc)
                    .put("subIntegral", OrderDetailDO::getSubIntegral)
                    .put("subRemark", OrderDetailDO::getSubRemark)
                    .build();

    /**
     * 查询条件，附表
     *
     * @return 条件构造器 LambdaQuerySqlWrapper
     */
    @Override
    public LambdaQueryWrapper<OrderDetailDO> toQueryWrapper() {
        LambdaQueryWrapper<OrderDetailDO> wrapper = new LambdaQueryWrapper<>();
        dealWithOrderBy(wrapper, COLUMNS);
        return wrapper;
    }

}
